package util;

import com.sun.xml.internal.messaging.saaj.util.Base64;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 *  @author: baoaijun
 *  @Date: 2020/12/7 13:35
 *  @Description: 文件打包协议
 */
public class FileProtocolUtil {

    // 文件类型（1：招标文件，2：投标文件，3：清单文件）
    private static final byte fileType = 1;

    // 文件类型字节长度，占1个字节
    private static int fileTypeByteLength = 1;

    // 版本号
    private static final byte version = 1;

    // 版本号字节长度，占1个字节
    private static final int versionByteLength = 1;

    // 文件大小，占4个字节
    private static final int fileSizeByteLength = 4;

    // 清单文件大小，占4个字节
    private static final int listFileSizeByteLength = 4;

    // 拓展文件大小，占2个字节
    private static final int jsonConfigSizeByteLength = 4;

    private static final java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();

    /***
     * 自定义文件打包
     * @param srcFilePath 文件部分存放路径
     * @param configJson 拓展部分
     * @param targetFilePath 打包文件存放路径
     * @return
     * @throws IOException
     */
    public static String write(String srcFilePath, String configJson, String listFilePath, String targetFilePath) throws Exception {
        File targetFile = new File(targetFilePath);
        if(!targetFile.getParentFile().exists()){
            targetFile.getParentFile().mkdirs();
        }
        OutputStream out = new FileOutputStream(targetFile);
        // 写入文件类型
        out.write(fileType);
        // 写入文件协议版本号
        out.write(version);
        // 写入文件大小（首先base64，然后写入）
        String fileBase64Str = Base64Util.encodeBase64File(srcFilePath);
        System.out.println(fileBase64Str.getBytes().length);
        out.write(ByteUtil.intToBytes(fileBase64Str.getBytes().length));
        // 写入清单文件大小
        String listFileBase64Str = Base64Util.encodeBase64File(listFilePath);
        System.out.println("listFileBase64Str.lenth" + fileBase64Str.getBytes().length);
        out.write(ByteUtil.intToBytes(listFileBase64Str.getBytes().length));
        // 写入拓展部分大小
        String encodedText = encoder.encodeToString(configJson.getBytes("UTF-8"));
        byte[] configJsonBytes = encodedText.getBytes("UTF-8");
        byte[] configJsonByteLength = ByteUtil.intToBytes(configJsonBytes.length);
        System.out.println(configJsonBytes.length);
        out.write(configJsonByteLength);
        // 写入文件
        out.write(fileBase64Str.getBytes());
        // 写入清单文件
        out.write(listFileBase64Str.getBytes());
        // 写入json配置
        out.write(configJsonBytes);
        out.close();
        return targetFilePath;
    }

    /***
     * 自定义文件读取
     * @param srcFilePath 自定义文件存放路径
     * @param targetFilePath 读取文件部分存放路径
     * @return
     * @throws IOException
     */
    public static Map read(String srcFilePath, String targetFilePath, String listTargetFilePath) throws Exception {
        Map resultMap = new HashMap();
        File targetFile = new File(srcFilePath);
        FileInputStream fileInputStream = new FileInputStream(targetFile);
        DataInputStream dis=new DataInputStream(fileInputStream);
        // 读取文件类型
        byte[] fileTypeByte = new byte[fileTypeByteLength];
        dis.read(fileTypeByte, 0, versionByteLength);
        int fileType = fileTypeByte[0];
        resultMap.put("fileType", fileType);
        // 读取版本号
        byte[] versionByte = new byte[versionByteLength];
        // read方法读取一定长度之后，被读取的数据就从流中去掉了，所以下次读取仍然从0开始
        dis.read(versionByte, 0, versionByteLength);
        int version = versionByte[0] & 0xFF;
        resultMap.put("version", version);
        // 读取文件大小
        byte[] fileSizeByte = new byte[fileSizeByteLength];
        dis.read(fileSizeByte, 0, fileSizeByteLength);
        int fileSize = ByteUtil.bytesToInt(fileSizeByte);
        resultMap.put("fileSize", fileSize);
        // 读取配置文件大小
        byte[] listFileSizeByte = new byte[listFileSizeByteLength];
        dis.read(listFileSizeByte, 0, listFileSizeByteLength);
        int listFileSize = ByteUtil.bytesToInt(listFileSizeByte);
        resultMap.put("listFileSize", listFileSize);
        // 读取json配置文件大小
        byte[] jsonSizeByte = new byte[jsonConfigSizeByteLength];
        dis.read(jsonSizeByte, 0, jsonConfigSizeByteLength);
        int jsonSize = ByteUtil.bytesToInt(jsonSizeByte);
        resultMap.put("jsonConfigSize", fileSize);
        // 读取文件
        byte[] pdfFileByte = new byte[fileSize];
        dis.read(pdfFileByte, 0, fileSize);
        String fileBase64Str = new String(pdfFileByte);
        Base64Util.decoderBase64File(fileBase64Str, targetFilePath);
        resultMap.put("targetFilePath", targetFilePath);
        // 读取清单文件
        byte[] listFilsByte = new byte[listFileSize];
        dis.read(listFilsByte, 0, listFileSize);
        String listFileBase64Str = new String(listFilsByte);
        Base64Util.decoderBase64File(listFileBase64Str, listTargetFilePath);
        resultMap.put("listTargetFilePath", listTargetFilePath);
        // 读取json配置
        byte[] jsonByte = new byte[jsonSize];
        dis.read(jsonByte, 0, jsonSize);
        // 写入前用base64编码过，所以读取需要用base解码才能读取到明文
        final java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
        String json = new String(decoder.decode(jsonByte), "UTF-8");
        resultMap.put("jsonConfig", json);
        return resultMap;
    }
}
